<!-- 目录 -->
<script lang="ts" setup>
import { ref, onActivated, onMounted, onUnmounted } from "vue";
import { getSimEngineProjectDirApi, deleteSimEngineFileApi, engineFileRenameApi, addSimEngineFileApi, updateFileMainApi, copySimEngineFileApi, moveSimEngineFileApi } from "@/common/apis/engine-library";
import { ElMessage, ElTree, ElInput } from "element-plus";
import type Node from "element-plus/es/components/tree/src/model/node";
import HandleContext from "@@/components/HandleContext/index.vue";
interface Props {
  sim_engine_id: string;
  item: any | undefined;
}
const props = defineProps<Props>();
const emit = defineEmits(["update:item"]);

interface Tree {
  [key: string]: any;
}

const route = useRoute();
const sim_engine_id = ref<string>((route.query.id as string) || props.sim_engine_id);
const treeRef = ref<InstanceType<typeof ElTree>>();
const inputRef = ref<InstanceType<typeof ElInput>>()
const copyFile = ref({})
let treeData = ref();
const defaultProps = {
  children: "children",
  label: "file_name",
  id: "file_id",
};

// 树结构拖拽配置
const draggable = {
  nodeKey: 'file_id',
  allowDrop: (draggingNode: any, dropNode: any, type: string) => {
    // 不允许拖拽到自身
    if (draggingNode.data.parent_id === dropNode.data.parent_id || draggingNode.data.file_id === dropNode.data.file_id) {
      return false;
    }
    return true;
  },
  allowDrag: (draggingNode: any) => {
    return true;
  }
};

const currentFile = ref<any>(null)
const handleCurrentChange = (data: any) => {
  showContextMenu.value = false
  if (data.file_name.indexOf(".pyc") != -1) {
    ElMessage.warning("该类型文件不可查看!");
    return;
  }
  if (data.is_binary === 1) {
    ElMessage.warning("该类型文件不可查看!");
    return;
  }
  if (data.type == 'dir') return
  currentFile.value = data
  emit('update:item', data)
}
// 找到isMain文件
const isMainSreach = (data: any, file_id: any, type: string) => {
  data.forEach((item: any, index: any) => {
    if (item.is_main === 1) {
      treeRef && treeRef.value.setCurrentKey(item.file_id)
      const node = treeRef.value.store.nodesMap[item.file_id];
      if (node) {
        handleCurrentChange(node.data);
      }
    }
    if (item.children && item.children.length > 0) {
      isMainSreach(item.children)
    }
  })
}
// 操作后的节点数据
const expandedKeys = ref<string[]>([]);

// 记录展开的节点
const handleNodeExpand = (data: any) => {
  if (!expandedKeys.value.includes(data.file_id)) {
    expandedKeys.value.push(data.file_id);
  }
};

// 记录折叠的节点
const handleNodeCollapse = (data: any) => {
  const index = expandedKeys.value.indexOf(data.file_id);
  if (index > -1) {
    expandedKeys.value.splice(index, 1);
  }
};

// 恢复展开的节点
const restoreExpandedNodes = () => {
  if (treeRef.value) {
    expandedKeys.value.forEach(key => {
      const node = treeRef.value.getNode(key);
      if (node) {
        node.expanded = true;
      }
    });
  }
};

const treeDataSreach = () => {
  getSimEngineProjectDirApi({
    sim_engine_id: sim_engine_id.value,
    parent_id: ''
  }).then(({ data }) => {
    data.forEach((item: any) => {
      if (!item.parent_id) {
        item.isRoot = true
      }
    })
    treeData.value = data
    setTimeout(() => {
      isMainSreach(treeData.value)
      // 恢复展开的节点
      restoreExpandedNodes();
    }, 100);
  })
}
treeDataSreach()
// 重置树数据并重新加载根节点
function reloadTree() {
  if (!treeRef.value) return;

  // 清除当前选中
  treeRef.value.setCurrentKey();

  // 重置内部状态
  treeRef.value.store.nodesMap = {};
  treeRef.value.store.root.childNodes = [];

  // 强制重新加载
  treeRef.value.store.root.loaded = false;
  treeRef.value.store.root.expanded = false;
  treeRef.value.store.root.expand();

  emit("update:item", undefined);
}
// onMounted(() => {
//   loadNodeData()
// })
onActivated(() => {
  if (sim_engine_id.value && sim_engine_id.value !== route.query.id) {
    reloadTree();
  }
});

const menuPosition = ref({ x: 0, y: 0 })
const showContextMenu = ref(false)
const currentNode = ref<any>(null)
const nameNode = ref('')

const handleContextMenu = (event: Event, node: Node, data: any) => {
  event.preventDefault()
  // 设置菜单位置
  menuPosition.value = {
    x: event.clientX,
    y: event.clientY,
  };
  // 设置当前节点
  currentNode.value = node;
  // 显示菜单
  showContextMenu.value = true;
};

const handleClickOutside = () => {
  showContextMenu.value = false
}
//  找到层级
const findFloor = (data: any, file_id: any, type: string) => {
  if (file_id === 'root') {
    if (type === 'doc' || type === 'folder') {
      treeData.value.push({
        file_name: '',
        is_directory: type === 'doc' ? 0 : 1,
        is_main: 0,
        parent_id: '',
        sim_engine_id: sim_engine_id.value,
        children: type === 'doc' ? null : [],
        isRename: 1
      })
      // 获取焦点
      setTimeout(() => {
        inputRef.value?.focus();
      }, 10);
    }
    if (type === 'paste') {
      // 判断是否为根节点,
      const copyData = {
        sim_engine_id: sim_engine_id.value,
        file_id: copyFile.value.file_id,
        target_id: file_id === 'root' ? "" : sim_engine_id.value
      }
      copySimEngineFileApi(copyData).then((res: any) => {
        if (copyFile.value.is_directory === 1) {
          getSimEngineProjectDirApi({
            sim_engine_id: sim_engine_id.value,
            parent_id: res.data.file_id
          }).then(({ data }) => {
            copyFile.value.children = data
            treeData.value.push(JSON.parse(JSON.stringify(copyFile.value)))
            treeData.value.children[treeData.value.length - 1].file_id = res.data.file_id
            treeData.value.children[treeData.value.length - 1].file_name = res.data.file_name
            // treeData.value.children.sort((a: any, b: any) => a.file_name.localeCompare(b.file_name))
            treeData.value.children.sort((a: any, b: any) => {
              if (a.is_directory !== b.is_directory) {
                return b.is_directory - a.is_directory;
              }
              return a.file_name.localeCompare(b.file_name);
            });
          })
        } else {
          copyFile.value.file_id = res.data.file_id
          copyFile.value.file_name = res.data.file_name
          if (file_id !== 'root') {
            // 不是根节点
            treeData.value.children.push(copyFile.value)
            // treeData.value.children.sort((a: any, b: any) => a.file_name.localeCompare(b.file_name))
            treeData.value.children.sort((a: any, b: any) => {
              if (a.is_directory !== b.is_directory) {
                return b.is_directory - a.is_directory;
              }
              return a.file_name.localeCompare(b.file_name);
            });
          } else {
            // 根节点
            treeData.value.push(copyFile.value)
            // treeData.value.sort((a: any, b: any) => a.file_name.localeCompare(b.file_name))
            treeData.value.sort((a: any, b: any) => {
              if (a.is_directory !== b.is_directory) {
                return b.is_directory - a.is_directory;
              }
              return a.file_name.localeCompare(b.file_name);
            });
          }
        }
      })
    }
    if (type === 'del') {
      treeData.value.pop()
    }
  } else {
    data.forEach((item: any, index: number) => {
      // 匹配目标数据
      if (item.file_id === file_id) {
        // 新建文件和新建文件夹
        if (type === 'doc' || type === 'folder') {
          if (item.is_directory === 1) {
            item.children = item.children ? item.children : []
            item.children.unshift({
              file_name: '',
              is_directory: type === 'doc' ? 0 : 1,
              is_main: 0,
              parent_id: item.file_id,
              sim_engine_id: item.sim_engine_id,
              children: type === 'doc' ? null : [],
              isRename: 1
            })
            const node = treeRef.value.getNode(file_id)
            if (node) {
              node.expanded = true
            }
            // 获取焦点
            setTimeout(() => {
              inputRef.value?.focus();
            }, 10);
          }
        }
        // 新建不输入文件名,失去焦点删除操作
        if (type === 'del') {
          item.children.shift()
        }
        // 删除文件和文件夹
        if (type === 'delete') {
          handleDelete(file_id).then(() => {
            data.splice(index, 1)
          })
        }
        // 设为主文件
        if (type === 'root') {
          updateFileMainApi(file_id).then(() => {
            ElMessage({
              message: '主文件更新成功',
              type: 'success',
            })
            treeDataSreach()
          })
        }
        // 复制文件
        if (type === 'copy') {
          copyFile.value = JSON.parse(JSON.stringify(item))
        }
        if (type === 'paste') {
          const copyData = {
            sim_engine_id: sim_engine_id.value,
            file_id: copyFile.value.file_id,
            target_id: file_id
          }
          copySimEngineFileApi(copyData).then((res: any) => {
            if (copyFile.value.is_directory === 1) {
              getSimEngineProjectDirApi({
                sim_engine_id: sim_engine_id.value,
                parent_id: res.data.file_id
              }).then(({ data }) => {
                copyFile.value.children = data
                item.children.unshift(JSON.parse(JSON.stringify(copyFile.value)))
                item.children[0].file_id = res.data.file_id
                item.children[0].file_name = res.data.file_name
                item.children.sort((a: any, b: any) => a.file_name.localeCompare(b.file_name))
                const node = treeRef.value.getNode(file_id)
                if (node) {
                  node.expanded = true
                }
              })
            } else {
              copyFile.value.file_id = res.data.file_id
              copyFile.value.file_name = res.data.file_name
              item.children.unshift(JSON.parse(JSON.stringify(copyFile.value)))
              item.children.sort((a: any, b: any) => a.file_name.localeCompare(b.file_name))
              const node = treeRef.value.getNode(file_id)
              if (node) {
                node.expanded = true
              }
            }
          })
        }
        // 重命名
        if (type === 'rename') {
          nameNode.value = item.file_name
          item.isRename = 1
          // 获取焦点
          setTimeout(() => {
            inputRef.value?.focus();
          }, 10);
        }
      }
      if (item.children && item.children.length > 0) {
        findFloor(item.children, file_id, type)
      }
    })
  }
}
const handleDelete = (id: any) => {
  return new Promise((resolve, reject) => {
    deleteSimEngineFileApi([id]).then(res => {
      ElMessage({
        message: '删除成功',
        type: 'success',
      })
      resolve('success')
    })
  })
}
const handleFocus = (event: Event) => {
  // 阻止事件冒泡，防止展开/折叠节点
  event.stopPropagation()
}
const handleBlur = (node: Node) => {
  if (node.data.file_id) {
    node.data.isRename = 0
    if (nameNode.value !== node.data.file_name) {
      engineFileRenameApi({ file_id: node.data.file_id, file_name: nameNode.value }).then(res => {
        node.data.file_name = JSON.parse(JSON.stringify(nameNode.value))
        nameNode.value = ''
      })
    }
  } else if (nameNode.value === '' && !node.data.file_id) {
    if (node.data.parent_id === '') {
      findFloor(treeData.value, 'root', 'del')
    } else {
      findFloor(treeData.value, node.data.parent_id, 'del')
    }
  } else if (!node.data.file_id && nameNode.value !== '') {
    const data = {
      sim_engine_id: sim_engine_id.value,
      file_name: nameNode.value,
      parent_id: node.data.parent_id,
      is_directory: node.data.is_directory
    }
    if (node.data.parent_id === '') {
      delete data.parent_id
    }
    addSimEngineFileApi(data).then((res: any) => {
    }).then((res: any) => {
      treeDataSreach()
      node.data.file_name = JSON.parse(JSON.stringify(nameNode.value))
      nameNode.value = ''
      node.data.isRename = 0
      node.data.file_id = res.data.file_id
      // setTimeout(() => {
      //   const nodeData = treeRef.value.getNode(node.data.file_id)
      //   if (node) {
      //     nodeData.checked = true
      //   }
      // }, 2000);
    })
  }
}
// 阻止点击输入框时的冒泡，防止触发树节点的展开/折叠
const handleClick = (event: Event) => {
  // 阻止事件冒泡
  event.stopPropagation()
}
// 菜单关闭
const handleClickCloseMenu = (file_id: string, type: string) => {
  findFloor(treeData.value, file_id, type)
  showContextMenu.value = false
}
const rootlick = (event: Event) => {
  // 设置菜单位置
  menuPosition.value = {
    x: event.clientX,
    y: event.clientY,
  };
  // 设置当前节点
  currentNode.value = {
    is_directory: 1,
    file_id: 'root'
  }
  showContextMenu.value = true
}
// 拖拽
const isDragging = ref(false);
// 拖拽文件
const handleDragOver = (event: DragEvent) => {
  event.preventDefault();
  event.stopPropagation();
  isDragging.value = true;
}
// 拖拽离开
const handleDragLeave = (event: DragEvent) => {
  event.preventDefault();
  event.stopPropagation();
  isDragging.value = false;
}
// 拖拽文件
const processFile = async (file: File, parentId: string = '') => {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('sim_engine_id', sim_engine_id.value);
  if (parentId) {
    formData.append('parent_id', parentId);
  }

  try {
    // 这里需要调用上传文件的API
    // await uploadSimEngineFileApi(formData);
    ElMessage.success(`文件 ${file.name} 上传成功`);
  } catch (error) {
    ElMessage.error(`文件 ${file.name} 上传失败`);
  }
}

// 拖拽文件夹
const processDirectory = async (entry: any, parentId: string = '') => {
  const reader = entry.createReader();
  const entries = await new Promise((resolve) => {
    reader.readEntries(resolve);
  });

  // 创建文件夹
  const folderData = {
    sim_engine_id: sim_engine_id.value,
    file_name: entry.name,
    parent_id: parentId,
    is_directory: 1
  };

  try {
    // 创建文件夹
    // const folderRes = await addSimEngineFileApi(folderData);
    // const newParentId = folderRes.data.file_id;

    // 处理文件夹内的文件
    for (const item of entries) {
      if (item.isDirectory) {
        await processDirectory(item, parentId);
      } else {
        const file = await new Promise((resolve) => {
          item.file(resolve);
        });
        await processFile(file, parentId);
      }
    }
  } catch (error) {
    ElMessage.error(`文件夹 ${entry.name} 创建失败`);
  }
}
// 拖拽文件
const handleDrop = async (event: DragEvent) => {
  event.preventDefault();
  event.stopPropagation();
  isDragging.value = false;

  const items = event.dataTransfer?.items;
  if (!items) return;

  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (item.kind === 'file') {
      const entry = item.webkitGetAsEntry();
      if (entry) {
        if (entry.isDirectory) {
          await processDirectory(entry);
        } else {
          const file = item.getAsFile();
          if (file) {
            await processFile(file);
          }
        }
      }
    }
  }

  // 刷新目录
  treeDataSreach();
}

// 处理拖拽结束事件
const handleDragEnd = async (draggingNode: any, dropNode: any, dropType: string) => {
  if (!dropNode) return;

  const draggingData = draggingNode.data;
  const dropData = dropNode.data;

  // 获取目标文件夹的file_id
  let targetId = '';
  if (dropType === 'inner') {
    // 如果是拖入文件夹内部
    targetId = dropData.file_id;
  } else {
    targetId = dropData.parent_id;
  }

  // 构建移动参数
  const moveParams = {
    file_id: draggingData.file_id,
    target_id: targetId,
    sim_engine_id: sim_engine_id.value
  }
  if (!dropData.parent_id && dropType !== 'inner') {
    delete moveParams.target_id
  }
  try {
    // 调用移动API
    await moveSimEngineFileApi(moveParams)
    ElMessage.success('移动成功');
    // 刷新目录树
    treeDataSreach();
  } catch (error) {
    ElMessage.error('移动失败');
    // 如果移动失败，恢复原来的位置
    treeDataSreach();
  }
}
// 新建文件和文件夹
const addFloder = (val: string) => {
  if (currentFile.value.is_directory === 1) {
    findFloor(treeData.value, currentFile.value.file_id, val)
  } else {
    if (currentFile.value.parent_id) {
      findFloor(treeData.value, currentFile.value.parent_id, val)
    } else {
      findFloor(treeData.value, 'root', val)
    }
  }
}
// 折叠
const flod = (val: string) => {
  const tree = treeRef.value
  if (!tree) return

  /** 递归遍历所有节点并 collapse() */
  const walk = (nodes: any[]) => {
    nodes.forEach(node => {
      if (node.expanded) node.collapse()       // 节点自带 collapse()
      if (node.childNodes?.length) walk(node.childNodes)
    })
  }

  walk(tree.store.root.childNodes)              // 对根节点数组递归
}
onMounted(() => {
  document.addEventListener("click", handleClickOutside);
})

onUnmounted(() => {
  document.removeEventListener("click", handleClickOutside);
})
</script>

<template>
  <!-- <div class="ce-catalog" @dragover="handleDragOver" @dragleave="handleDragLeave" @drop="handleDrop"
    :class="{ 'dragover': isDragging }"> -->
  <div class="ce-catalog">
    <div class="cec-header">
      <div class="uno-flex-center">
        <div class="file-iconify-item">
          <el-icon>
            <Files />
          </el-icon>
        </div>
        <span class="cec-header-title">文件</span>
      </div>
      <div class="cec-header-right">
        <el-tooltip class="box-item" effect="dark" content="折叠" placement="top">
          <el-button type="primary" link @click.stop="flod">
            <SvgIcon name="code-zhedie" />
          </el-button>
        </el-tooltip>
        <el-tooltip class="box-item" effect="dark" content="新建文件" placement="top">
          <el-button type="primary" link @click.stop="addFloder('doc')">
            <SvgIcon name="code-file" />
          </el-button>
        </el-tooltip>
        <el-tooltip class="box-item" effect="dark" content="新建文件夹" placement="top">
          <el-button type="primary" link @click.stop="addFloder('folder')">
            <SvgIcon name="code-folder" />
          </el-button>
        </el-tooltip>
      </div>
    </div>
    <div class="cec-content" @contextmenu.prevent.stop="rootlick">
      <el-tree style="height: 100%" ref="treeRef" :props="defaultProps" :data="treeData" node-key="file_id"
        highlight-current @node-click="handleCurrentChange" @node-contextmenu="handleContextMenu" draggable
        :allow-drop="draggable.allowDrop" :allow-drag="draggable.allowDrag" @node-drag-end="handleDragEnd"
        @node-expand="handleNodeExpand" @node-collapse="handleNodeCollapse">
        <template #default="{ node, data }">
          <div class="custom-tree-node">
            <SvgIcon v-if="node.data.is_directory === 1" class="custom-tree-icon folder" name="folder" />
            <SvgIcon v-else-if="node.data.is_directory === 0" class="custom-tree-icon checklist" name="checklist" />
            <span class="custom-tree-node" :title="node.label">
              <template v-if="!data.isRename">
                {{ node.label }}
                <SvgIcon v-if="data.is_main === 1" name="code-zhuliebiao" />
              </template>
              <el-input v-else v-model="nameNode" @focus="handleFocus" @blur="handleBlur(node)" @click="handleClick"
                @mousedown.stop ref="inputRef" @keydown.enter="handleBlur(node)" />
            </span>
          </div>
        </template>
      </el-tree>

      <!-- 将菜单移到树组件外部 -->
      <HandleContext v-if="showContextMenu" :data="currentNode" class="handle-context" :style="{
        left: `${menuPosition.x}px`,
        top: `${menuPosition.y}px`,
      }" @close="handleClickCloseMenu" />
    </div>
  </div>
</template>
<style lang="scss" scoped>
@import "@@/assets/styles/mixins.scss";

.cec-header {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--main-padding) var(--main-padding) 0 var(--main-padding);
}

.uno-flex-center {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.file-iconify-item {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border-radius: 4px;
  margin-right: 8px;
  // text-align: center;
}

.cec-header-title {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.ce-catalog {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  transition: all 0.3s ease;

  &.dragover {
    border: 2px dashed var(--el-color-primary);
    background-color: rgba(var(--el-color-primary-rgb), 0.1);
    position: relative;

    &::after {
      content: '拖拽文件或文件夹到此处上传';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      color: var(--el-color-primary);
      font-size: 16px;
      pointer-events: none;
    }
  }
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  position: relative;
  padding-right: 8px;
}

.cec-content {
  flex: 1;
  height: calc(100% - 82px);
  overflow: auto;
  padding: 0 0 var(--main-padding) var(--main-padding);
  @extend %scrollbar;
}

.dark-blue .el-tree {
  --el-tree-node-hover-bg-color: #27365e;
  background-color: transparent;
}

:deep(.el-tree-node__content) {
  height: 32px !important;
  line-height: 32px !important;
  border-radius: 4px;
  margin-right: 10px;

  &.is-drop-inner {
    background-color: rgba(var(--el-color-primary-rgb), 0.1);
  }
}

:deep(.el-tree-node.is-drop-inner > .el-tree-node__content) {
  background-color: rgba(var(--el-color-primary-rgb), 0.1);
}

.custom-tree-node {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.custom-tree-icon {
  margin-right: 10px;
  margin-left: 2px;

  &.checklist {
    fill: #8fb9fe !important;
  }

  &.folder {
    fill: #ffca28 !important;
  }

  &.folder-blue {
    fill: #8fb9fe !important;
  }
}

.handle-context {
  position: fixed;
  z-index: 9999;
}

.cec-header-right {
  .el-button {
    &.is-disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
  }
}
</style>
